// Copyright 2020 morgine.com. All rights reserved.

package handlers

import (
	"errors"
	"gitee.com/tugoer/psys/models"
	"gitee.com/tugoer/psys/services"
	"github.com/gin-gonic/gin"
	orm "github.com/jinzhu/gorm"
	"golang.org/x/crypto/bcrypt"
)

var ErrUsernameOrPasswordIncorrect = errors.New("username or password incorrect")
var ErrAdminUsernameAlreadyRegistered = errors.New("admin username already registered")
var ErrAdminNotFound = errors.New("admin not found")
var ErrPasswordIsIllegal = errors.New("admin password is illegal")

func Login(ctx *gin.Context) {
	a := &models.Admin{}
	err := ctx.Bind(a)
	if err != nil {
		ctx.JSON(200, NewMessage("warning", err.Error()))
	} else {
		exist, err := SignIn(a.Username, a.Password)
		if err != nil {
			ctx.JSON(200, NewMessage("warning", err.Error()))
		} else {
			auth, err := EncodeBasicAuthorization(a.Username, a.Password)
			if err != nil {
				ctx.JSON(200, NewMessage("warning", err.Error()))
			} else {
				SetAdminToSession(a.Username, exist)
				ctx.JSON(200, gin.H{
					"admin":         exist,
					"authorization": auth,
				})

			}
		}
	}
}

func Logout(ctx *gin.Context) {
	auth := GetAuthorization(ctx)
	if auth != "" {
		username, _, _ := DecodeBasicAuthorization(auth)
		if username != "" {
			DelAdminFromSession(username)
			ctx.JSON(200, NewMessage("success", "已退出"))
		}
	}
}

func GetInfo(ctx *gin.Context) {
	admin := GetAdminFromSession(ctx)
	if admin != nil {
		ctx.JSON(200, gin.H{"admin": admin})
	}
}

func SignIn(username, password string) (*models.Admin, error) {
	admin, err := GetAdmin(username)
	if err != nil {
		if err == ErrAdminNotFound {
			return nil, ErrUsernameOrPasswordIncorrect
		}
		return nil, err
	}
	err = bcrypt.CompareHashAndPassword([]byte(admin.Password), []byte(password))
	if err != nil {
		return nil, ErrUsernameOrPasswordIncorrect
	}
	return admin, nil
}

func Register(username, password string) (*models.Admin, error) {
	admin, _ := GetAdmin(username)
	if admin != nil && admin.ID > 0 {
		return nil, ErrAdminUsernameAlreadyRegistered
	}
	pass, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return nil, ErrPasswordIsIllegal
	}
	admin = &models.Admin{Username: username, Password: string(pass)}
	err = services.Gorm.Create(admin).Error
	return admin, err
}

func GetAdmin(username string) (*models.Admin, error) {
	var admin = &models.Admin{}
	err := services.Gorm.Model(admin).Where("username=?", username).First(admin).Error
	if err != nil {
		if err == orm.ErrRecordNotFound {
			return nil, ErrAdminNotFound
		}
		return nil, err
	}
	return admin, nil
}
